package com.inifitness.common.log;

import java.lang.reflect.Method;

import com.inifitness.common.annotations.BizLog;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.stereotype.Component;

/**
 * 业务日志处理切面
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @see com.inifitness.common.annotations.BizLog
 * @since 2024/04/18 11:00:00
 */
@Aspect
@Component
@Log4j2
public class BizLogAspect {

  @Before("execution(* com..*Controller.*(..))")
  public void doBeforeMethod(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    Class<?> classTarget = joinPoint.getTarget().getClass();
    Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
    log.debug("class={},method={}",className,methodName);
    Tag tag = classTarget.getAnnotation(Tag.class);
    try {
      Method objMethod = classTarget.getMethod(methodName, parameterTypes);
      log.info("-------------------");
      Operation operation = objMethod.getAnnotation(Operation.class);

      if (tag != null && operation != null) {
        log.info(()-> MessageFormatter.format("执行操作: {}-{}", tag.name(), operation.summary()));
      }
    } catch (NoSuchMethodException e) {
      log.warn("获取操作日志时出现错误，未找到方法", e);
    }
  }

  /**
   * 处理完请求后执行
   *
   * @param joinPoint 切点
   */
  @AfterReturning(pointcut = "@annotation(bizLog)", returning = "jsonResult")
  public void doAfterReturning(JoinPoint joinPoint, BizLog bizLog, Object jsonResult) {
    handleLog(joinPoint, bizLog, null, jsonResult);
  }

  /**
   * 拦截异常操作
   *
   * @param joinPoint 切点
   * @param e         异常
   */
  @AfterThrowing(value = "@annotation(bizLog)", throwing = "e")
  public void doAfterThrowing(JoinPoint joinPoint, BizLog bizLog, Exception e) {
    handleLog(joinPoint, bizLog, e, null);
  }

  protected void handleLog(final JoinPoint joinPoint, BizLog bizLog, final Exception e,
      Object jsonResult) {
    try {
      // 获取当前的用户
      String className = joinPoint.getTarget().getClass().getName();
      String methodName = joinPoint.getSignature().getName();

      log.debug("操作日志记录-调用类{}", className);
      log.debug("操作日志记录-调用方法{}", methodName);
      log.debug("操作日志记录-返回结果{}", jsonResult);
    } catch (Exception exp) {
      // 记录本地异常日志
      log.error("异常信息:{}", exp.getMessage(),exp);
    }
  }
}
